package cn.wolfcode.shiro;

import cn.wolfcode.domain.Employee;
import cn.wolfcode.domain.Role;
import cn.wolfcode.mapper.PermissionMapper;
import cn.wolfcode.mapper.RoleMapper;
import cn.wolfcode.service.IEmployeeService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;


@Component
public class CrmRealm extends AuthorizingRealm {

    @Autowired
    private IEmployeeService employeeService;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 覆写设置凭证匹配器方法,通过注入交给spring容器管理,通过配置加密方法告诉shiro框架使用的加密方法是什么
     */
    @Autowired//属性注入,autowired也可以贴在set方法上
    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        super.setCredentialsMatcher(credentialsMatcher);
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取填写的用户名
        //token.getCredentials();//这是获取密码的,现在用不到
        Object username = token.getPrincipal();
        //判断是否存在数据库中的
        Employee employee = employeeService.selectByName((String) username);
        if (employee!=null){
            //先获取employee对象中的status属性,潘墩是否为禁用状态
            if (!employee.isStatus()) {
                //当为禁用状态时,抛出异常
                throw new DisabledAccountException();
            }
            //如果匹配上,则返回AuthenticationInfo对象
            return new SimpleAuthenticationInfo(employee,//数据库中的账号
                    employee.getPassword(),//数据库中的密码
                    ByteSource.Util.bytes(username),//加盐
                    "CrmRealm");//使用的是哪一个realm
        }

        return null;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        System.out.println("=============================进来了==============================");

        //创建授权信息对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前登录的用户(主体)
        Subject subject = SecurityUtils.getSubject();
        //获取当前登录用户的身份信息(之前传的是对象,这里可以拿到对象,之前传的是账号,这里拿到的是账号)
        Employee employee = (Employee) subject.getPrincipal();
        //首先判断当前登录用户是否为超级管理员
        if (employee.isAdmin()) {
            //如果为超管则不需要查询权限和角色,其拥有所有的角色和权限
             info.addRole("ADMIN");//加入admin的角色
             info.addStringPermission("*:*");//表示拥有所有角色
        }else {
            //然后根据当前登录用户的id去获取给用户所拥有的所有角色的编码
            List<Role> roles = roleMapper.selectRolesByEmpId(employee.getId());
            //新建一个数组用来存放当前用户所拥有角色的编码sn
            ArrayList<String> roleSnList = new ArrayList<>();
            //遍历roles
            for (Role role : roles) {
                roleSnList.add(role.getSn());
            }
            //将sn的数组存入info中
            info.addRoles(roleSnList);
            //获取当前用户的权限表达式
            List<String> expressions = permissionMapper.selectByEmpId(employee.getId());
            info.addStringPermissions(expressions);
        }

        return info;
    }


}
